package com.qingyun.form.internal.render

import android.annotation.SuppressLint
import android.content.Context
import androidx.fragment.app.FragmentManager
import com.qingyun.form.base.FormGroupAdapter
import com.qingyun.form.base.FormInputType
import com.qingyun.form.internal.IFormDataBinding
import com.qingyun.form.internal.TopLinearSmoothScroller
import com.qingyun.form.items.BaseFormItem
import com.qingyun.form.items.CheckBoxFormItem
import com.qingyun.form.items.DateFormItem
import com.qingyun.form.items.EditTextFormItem
import com.qingyun.form.items.GroupTitleFormItem
import com.qingyun.form.items.RadioGroupFormItem
import com.qingyun.form.items.SelectFormItem
import com.qingyun.form.provider.FormDataProvider
import org.json.JSONObject

open class FormRender(
    private val context: Context,
    private val adapter: FormGroupAdapter,
    private val fragmentManager: FragmentManager,
) : IFormRender {
    /** 表单组件 */
    private val formGroup = adapter.formGroup
    protected val smoothScroller by lazy {
        TopLinearSmoothScroller(context)
    }

    override fun render() {
        formGroup.attachRender(this)
    }


    open fun addSelect(
        provider: FormDataProvider,
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        dialogTitle: String? = null,
        parent: BaseFormItem? = null,
    ): SelectFormItem {
        return SelectFormItem(provider, label, name, value, required).addToFormGroup(parent) {
            it.dialogTitle = dialogTitle
        }
    }

    open fun addCheckBox(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): CheckBoxFormItem {
        val itemValue = when (value) {
            "0" -> "false"
            "1" -> "true"
            else -> value
        }
        return CheckBoxFormItem(label, name, itemValue, required).addToFormGroup(parent)
    }

    open fun addDate(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): DateFormItem {
        return DateFormItem(label, name, value, required).addToFormGroup(parent)
    }

    open fun addRadioGroup(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): RadioGroupFormItem {
        val itemValue = when (value) {
            "0" -> "false"
            "1" -> "true"
            else -> value
        }
        return RadioGroupFormItem(label, name, itemValue, required).addToFormGroup(parent)
    }

    open fun addRadioGroupChild(
        parent: BaseFormItem,
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
    ): RadioGroupFormItem {
        return addRadioGroup(label, name, value, required, parent)
    }

    open fun addEditTextChild(
        parent: BaseFormItem,
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
    ): EditTextFormItem {
        return addEditText(label, name, value, required, parent)
    }

    open fun addEditText(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): EditTextFormItem {
        return addEditTextInternal(FormInputType.Text, label, name, value, required, parent)
    }

    open fun addMultiEditText(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): EditTextFormItem {
        return addEditTextInternal(FormInputType.MultiText, label, name, value, required, parent)
    }

    open fun addPhoneEditText(
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): EditTextFormItem {
        return addEditTextInternal(FormInputType.Phone, label, name, value, required, parent)
    }

    open fun addNumberEditTextChild(
        parent: BaseFormItem,
        isDecimal: Boolean = false,
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
    ): EditTextFormItem {
        return addNumberEditText(isDecimal, label, name, value, required, parent)
    }

    open fun addNumberEditText(
        isDecimal: Boolean = false,
        label: String,
        name: String,
        value: String? = null,
        required: Boolean = false,
        parent: BaseFormItem? = null,
    ): EditTextFormItem {
        val inputType = if (isDecimal) {
            FormInputType.Decimal
        } else {
            FormInputType.Number
        }
        return addEditTextInternal(inputType, label, name, value, required, parent)
    }

    protected fun addEditTextInternal(
        inputType: FormInputType,
        label: String,
        name: String,
        value: String?,
        required: Boolean,
        parent: BaseFormItem?,
    ): EditTextFormItem {
        return EditTextFormItem(inputType, label, name, value, required).addToFormGroup(parent)
    }

    open fun addGroupTitle(label: String): GroupTitleFormItem {
        return GroupTitleFormItem(label).addToFormGroup()
    }

    protected fun <T : BaseFormItem> T.addToFormGroup(
        parent: BaseFormItem? = null,
        block: ((T) -> Unit)? = null,
    ): T {
        block?.invoke(this)
        val rootFormGroup = this@FormRender.formGroup
        this.formGroup = rootFormGroup
        val binding = this@FormRender as? IFormDataBinding
        this.onFormRender(fragmentManager, binding)
        if (parent == null) {
            rootFormGroup.addItem(this)
        } else {
            rootFormGroup.addChildren(parent, this)
        }
        return this
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onNeedRefresh() {
        if (!canRefresh()) {
            return
        }
        adapter.notifyDataSetChanged()
    }

    private fun canRefresh(): Boolean {
        val recyclerView = adapter.recyclerView ?: return false
        if (recyclerView.isComputingLayout) {
            return false
        }
        if (recyclerView.layoutManager?.isSmoothScrolling == true) {
            return false
        }
        return true
    }

    override fun onFormItemInserted(
        item: BaseFormItem?,
        position: Int,
    ) {
        if (!canRefresh()) {
            return
        }
        adapter.notifyItemInserted(position)
    }

    override fun onFormItemRemoved(
        item: BaseFormItem?,
        position: Int,
        count: Int,
    ) {
        if (!canRefresh()) {
            return
        }
        if (count > 0) {
            adapter.notifyItemRangeRemoved(position, count)
        } else {
            adapter.notifyItemRemoved(position)
        }
    }

    override fun onFormItemUpdated(index: Int) {
        if (!canRefresh()) {
            return
        }
        adapter.notifyItemChanged(index)
    }

    override fun highlight(formItem: BaseFormItem?) {
        formItem ?: return
        val recyclerView = adapter.recyclerView ?: return
        smoothScroller.scrollNow(recyclerView, formItem.position)
    }

    fun toJson(): String {
     return  formGroup.toJson()
    }
}